#include "stdafx.h"
#include "CmdHandler.h"
#include "VanException.h"
#include "CmdServer.h"
#include <string.h>
#include <stdlib.h>
#include "common.h"
#include "Utils.h"
#include "McuCmd.h"

CmdHandler* CmdHandler::m_pInstance = NULL;

CmdHandler::CmdHandler()
{
}

CmdHandler::~CmdHandler()
{
}

CmdHandler* CmdHandler::Instance()
{
	if (NULL == m_pInstance) {
		m_pInstance = new CmdHandler();
	}

	return m_pInstance;
}

void CmdHandler::Handle(CmdClient* client, Packet* pPacket)
{
	int nCmd = pPacket->GetCMD();

	switch (nCmd)
	{
	case PCID_GET_VERSION:
		GetVersion(client, pPacket);
		break;
	case PCID_ACC_GET:
		OnGetAcc(client, pPacket);
		break;
	case PCID_POWER_CTRL:
		OnPowerCtrl(client, pPacket);
		break;
	case PCID_GET_POWER_VOLTAGE:
		OnGetPowerVoltage(client, pPacket);
		break;
	case PCID_CAN_COUNT:
		OnCanCount(client, pPacket);
		break;
	case PCID_CAN_WRITE:
		OnCanWrite(client, pPacket);
		break;
	case PCID_CAN_GET_BAUDRATE:
		OnCanBaudrateGet(client, pPacket);
		break;
	case PCID_CAN_SET_BAUDRATE:
		OnCanBaudrateSet(client, pPacket);
		break;
	case PCID_CAN_FILTER_CTRL:
		OnCanFilterCtrl(client, pPacket);
		break;
	case PCID_CAN_HW_FILTER_ADD:
		OnCanHwFilterAdd(client, pPacket);
		break;
	case PCID_CAN_HW_FILTER_CLEAR:
		OnCanHwFilterClear(client, pPacket);
		break;
	case PCID_CAN_SW_FILTER_ADD:
		OnCanSwFilterAdd(client, pPacket);
		break;
	case PCID_CAN_SW_FILTER_CLEAR:
		OnCanSwFilterClear(client, pPacket);
		break;
	case PCID_BLOCK_COUNT:
		OnBlockGetCount(client, pPacket);
		break;
	case PCID_BLOCK_WRITE:
		OnBlockWrite(client, pPacket);
		break;
	case PCID_BLOCK_READ:
		OnBlockRead(client, pPacket);
		break;
	case PCID_INPUT_COUNT:
		OnInputGetCount(client, pPacket);
		break;
	case PCID_INPUT_GET:
		OnInputGet(client, pPacket);
		break;
	case PCID_OUTPUT_COUNT:
		OnOutputGetCount(client, pPacket);
		break;
	case PCID_OUTPUT_GET:
		OnOutputGet(client, pPacket);
		break;
	case PCID_OUTPUT_SET:
		OnOutputSet(client, pPacket);
		break;
	case PCID_UPDATE_MCU:
		UpdateMcu(client, pPacket);
		break;
	case PCID_CALLBACK_SET:
		OnCallbackSet(client, pPacket);
		break;
	case PCID_PUT_RTC:
		OnCallbackSet(client, pPacket);
		break;

	default:
		break;
	}

	delete pPacket;
}

void CmdHandler::GeneralResp(UvClient* client, byte cmd, byte result)
{
	byte body[2];
	body[0] = cmd;
	body[1] = result;

	Packet packet(0x81);
	packet.SetBody(body, 2);
	packet.Build();
	
	client->Write((const char *)packet.GetBuffer(), packet.GetLength(), true, false);
}

void CmdHandler::SpecialResp(UvClient* client, byte cmd, byte* pData, int length)
{
	Packet packet(cmd + 0x80);
	packet.SetBody(pData, length);
	packet.Build();
	
	client->Write((const char *)packet.GetBuffer(), packet.GetLength(), true, false);
}

void CmdHandler::GetVersion(UvClient* client, Packet* pPacket)
{
	string str = McuCmd::GetVersion();
	SpecialResp(client, pPacket->GetCMD(), (byte*)str.c_str(), str.length());
}

void CmdHandler::OnGetAcc(UvClient* client, Packet* pPacket)
{
	byte val = (byte)McuCmd::GetAccState();
	SpecialResp(client, pPacket->GetCMD(), &val, 1);
}

void CmdHandler::OnPowerCtrl(UvClient* client, Packet* pPacket)
{
	bool bRet = McuCmd::PowerCtrl(pPacket->GetBody()[0]);

	GeneralResp(client, pPacket->GetCMD(), bRet ? 0 : 3);
}

void CmdHandler::OnGetPowerVoltage(UvClient* client, Packet* pPacket)
{
	int voltage = McuCmd::GetPowerVoltage();
	uint8_t buf[4];
	Utils::WriteInt(buf, voltage, 4);
	
	SpecialResp(client, pPacket->GetCMD(), buf, 4);
}

void CmdHandler::OnCanCount(UvClient* client, Packet* pPacket)
{
	byte count = McuCmd::GetCanCount();	
	SpecialResp(client, pPacket->GetCMD(), &count, 1);
}

void CmdHandler::OnCanWrite(UvClient* client, Packet* pPacket)
{
	const byte* pBuf = pPacket->GetBody();
	uint32_t id = Utils::ReadInt(pBuf+1, 4);

	McuCmd::CanWrite(pBuf[0], id, pBuf + 6, pBuf[5]);
}

void CmdHandler::OnCanBaudrateGet(UvClient* client, Packet* pPacket)
{
	int baudrate = McuCmd::GetCanSpeed(pPacket->GetBody()[0]);
	byte buf[4];
	Utils::WriteInt(buf, baudrate, 4);
	
	SpecialResp(client, pPacket->GetCMD(), buf, 4);
}

void CmdHandler::OnCanBaudrateSet(UvClient* client, Packet* pPacket)
{
	const byte* pBuf = pPacket->GetBody();
	
	uint32_t baudrate = Utils::ReadInt(pBuf+1, 4);
	bool bRet = McuCmd::SetCanSpeed(pBuf[0], baudrate);
	
	GeneralResp(client, pPacket->GetCMD(), bRet ? 0 : 1);
}

void CmdHandler::OnCanFilterCtrl(UvClient* client, Packet* pPacket)
{
	const byte* pBuf = pPacket->GetBody();
	
	bool bRet = McuCmd::CanFilterCtrl(pBuf[0], pBuf[1]);
	
	GeneralResp(client, pPacket->GetCMD(), bRet ? 0 : 1);
}

void CmdHandler::OnCanHwFilterAdd(UvClient* client, Packet* pPacket)
{
	const byte* pBuf = pPacket->GetBody();
	
	uint32_t id = Utils::ReadInt(pBuf+1, 4);
	uint32_t mask = Utils::ReadInt(pBuf+5, 4);
	
	bool bRet = McuCmd::CanHwFilterAdd(pBuf[0], id, mask);
	
	GeneralResp(client, pPacket->GetCMD(), bRet ? 0 : 1);
}

void CmdHandler::OnCanHwFilterClear(UvClient* client, Packet* pPacket)
{
	bool bRet = McuCmd::CanHwFilterClear(pPacket->GetBody()[0]);
	GeneralResp(client, pPacket->GetCMD(), bRet ? 0 : 1);
}

void CmdHandler::OnCanSwFilterAdd(UvClient* client, Packet* pPacket)
{
	const byte* pBuf = pPacket->GetBody();
	
	uint32_t id = Utils::ReadInt(pBuf+1, 4);
	uint32_t mask = Utils::ReadInt(pBuf+5, 4);
	
	bool bRet = McuCmd::CanSwFilterAdd(pBuf[0], id, mask);
	
	GeneralResp(client, pPacket->GetCMD(), bRet ? 0 : 1);
}

void CmdHandler::OnCanSwFilterClear(UvClient* client, Packet* pPacket)
{
	bool bRet = McuCmd::CanSwFilterClear(pPacket->GetBody()[0]);
	GeneralResp(client, pPacket->GetCMD(), bRet ? 0 : 1);
}

void CmdHandler::OnBlockGetCount(UvClient* client, Packet* pPacket)
{
	byte count = (byte)McuCmd::GetBlockCount();
	SpecialResp(client, pPacket->GetCMD(), &count, 1);
}

void CmdHandler::OnBlockWrite(UvClient* client, Packet* pPacket)
{
	const byte* pBuf = pPacket->GetBody();
	
	bool bRet = McuCmd::BlockWrite(pBuf[0], pBuf + 2, pBuf[1]);
	GeneralResp(client, pPacket->GetCMD(), bRet ? 0 : 1);
}

void CmdHandler::OnBlockRead(UvClient* client, Packet* pPacket)
{
	const byte* pBuf = pPacket->GetBody();
	
	byte* p = new byte[pBuf[1]];
	if (NULL == p) {
		GeneralResp(client, pPacket->GetCMD(), 1);
		return;
	}
	
	McuCmd::BlockRead(pBuf[0], p, pBuf[1]);
	SpecialResp(client, pPacket->GetCMD(), p, pBuf[1]);
}

void CmdHandler::OnInputGetCount(UvClient* client, Packet* pPacket)
{
	byte count = (byte)McuCmd::GetInputCount();
	SpecialResp(client, pPacket->GetCMD(), &count, 1);
}

void CmdHandler::OnInputGet(UvClient* client, Packet* pPacket)
{
	byte val = (byte)McuCmd::InputGet(pPacket->GetBody()[0]);
	SpecialResp(client, pPacket->GetCMD(), &val, 1);
}

void CmdHandler::OnOutputGetCount(UvClient* client, Packet* pPacket)
{
	byte count = (byte)McuCmd::GetOutputCount();
	SpecialResp(client, pPacket->GetCMD(), &count, 1);
}

void CmdHandler::OnOutputGet(UvClient* client, Packet* pPacket)
{
	byte val = (byte)McuCmd::OutputGet(pPacket->GetBody()[0]);
	SpecialResp(client, pPacket->GetCMD(), &val, 1);
}

void CmdHandler::OnOutputSet(UvClient* client, Packet* pPacket)
{
	const byte* pBuf = pPacket->GetBody();
	
	bool bRet = McuCmd::OutputSet(pBuf[0], pBuf[1]);
	GeneralResp(client, pPacket->GetCMD(), bRet ? 0 : 1);
}

void CmdHandler::UpdateMcu(UvClient* client, Packet* pPacket)
{
	string path((const char*)pPacket->GetBody(), pPacket->GetBodySize());

	bool bRet = McuCmd::PowerCtrl(0);
	if (!bRet) {
		GeneralResp(client, pPacket->GetCMD(), 1);
		return;
	}

	bRet = CmdServer::Instance()->UpdateMcu(path.c_str());
	GeneralResp(client, pPacket->GetCMD(), bRet ? 0 : 1);
}

void CmdHandler::OnCallbackSet(CmdClient* client, Packet* pPacket)
{
	client->SetFilter(pPacket->GetBody()[0]);
	GeneralResp(client, pPacket->GetCMD(), 0);
}
